import {createVNode, render} from 'vue';
import NotificationConstructor from './index.vue'

const notifications = {
  'top': [],
  'bottom': [],
};
let GAP_SIZE = 16;
let seed = 1;
export const notify = function (options) {
  const position = options.position || 'top';

  let verticalOffset = options.offset || 0;
  notifications[position].forEach(({vm}) => {
    verticalOffset += (vm.el.offsetHeight || 0) + GAP_SIZE;
  });
  verticalOffset += GAP_SIZE;

  const id = 'notification_' + seed++;
  const userOnClose = options.onClose;
  options = {
    ...options,
    onClose: () => {
      close(id, position, userOnClose)
    },
    offset: verticalOffset,
    id,
  }

  const container = document.createElement('div');
  const vm = createVNode(NotificationConstructor, options);

  vm.props.onDestroy = () => {
    render(null, container);
  };

  render(vm, container);
  notifications[position].push({vm});
  document.body.appendChild(container.firstElementChild);
  return {
    close: () => {
      vm.component.proxy.visible = false;
    }
  }
}

export function close(
  id, position, userOnClose
) {
  // maybe we can store the index when inserting the vm to notification list.
  const orientedNotifications = notifications[position]
  const idx = orientedNotifications.findIndex(({ vm }) => vm.component.props.id === id)
  if (idx === -1) return
  const { vm } = orientedNotifications[idx]
  if (!vm) return
  // calling user's on close function before notification gets removed from DOM.
  userOnClose?.(vm)

  // note that this is called @before-leave, that's why we were able to fetch this property.
  const removedHeight = vm.el.offsetHeight
  const verticalPos = position.split('-')[0]
  orientedNotifications.splice(idx, 1)
  const len = orientedNotifications.length
  if (len < 1) return
  // starting from the removing item.
  for (let i = idx; i < len; i++) {
    // new position equals the current offsetTop minus removed height plus 16px(the gap size between each item)
    const { el, component } = orientedNotifications[i].vm
    component.props.offset = parseInt(el.style[verticalPos], 10) - removedHeight - GAP_SIZE
  }
}
